# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1046.15.56 -> 1.1046.15.57 # drivers/char/mem.c 1.35.1.4 -> 1.35.1.5 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/06/04 davidm@tiger.hpl.hp.com 1.1046.15.57 # Fix up drivers/char/mem.c some more. # -------------------------------------------- # diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Mon Sep 22 13:00:25 2003 +++ b/drivers/char/mem.c Mon Sep 22 13:00:25 2003 @@ -105,6 +105,39 @@ } +static ssize_t do_write_io(struct file * file, void *p, unsigned long realp, + const char * buf, size_t count, loff_t *ppos) +{ + ssize_t written; + char byte; + size_t i; + + /* this is slow but nobody cares... */ + + written = 0; +#if defined(__sparc__) || (defined(__mc68000__) && defined(CONFIG_MMU)) + /* we don't have page 0 mapped on sparc and m68k.. */ + if (realp < PAGE_SIZE) { + unsigned long sz = PAGE_SIZE-realp; + if (sz > count) sz = count; + /* Hmm. Do something? */ + buf+=sz; + p+=sz; + count-=sz; + written+=sz; + } +#endif + for (i = 0; i < count; ++i) { + if (get_user(byte, buf + i)) + return -EFAULT; + writeb(byte, p + i); + } + written += count; + *ppos += written;; + return written; +} + + /* * This funcion reads the *physical* memory. The f_pos points directly to the * memory location. @@ -114,7 +147,6 @@ { unsigned long p = *ppos; unsigned long end_mem; - int uncached; ssize_t read; void *addr; @@ -140,15 +172,22 @@ } } #endif - uncached = uncached_access(file, (unsigned long) p); - if (uncached) - addr = ioremap(p, count); - else - addr = __va(p); - if (copy_to_user(buf, addr, count)) - return -EFAULT; - if (uncached) + if (uncached_access(file, (unsigned long) p)) { + char byte; + size_t i; + + if (!(addr = ioremap(p, count))) + return -EFAULT; + /* this is slow but nobody cares... */ + for (i = 0; i < count; ++i) { + byte = readb(addr + i); + if (put_user(byte, buf + i)) + return -EFAULT; + } iounmap(addr); + } else + if (copy_to_user(buf, __va(p), count)) + return -EFAULT; read += count; *ppos += read; return read; @@ -159,7 +198,6 @@ { unsigned long p = *ppos; unsigned long end_mem; - int uncached; ssize_t ret; void *addr; @@ -168,14 +206,13 @@ return 0; if (count > end_mem - p) count = end_mem - p; - uncached = uncached_access(file, (unsigned long) p); - if (uncached) - addr = ioremap(p, count); - else - addr = __va(p); - ret = do_write_mem(file, addr, p, buf, count, ppos); - if (uncached) + if (uncached_access(file, (unsigned long) p)) { + if (!(addr = ioremap(p, count))) + return -EFAULT; + ret = do_write_io(file, addr, p, buf, count, ppos); iounmap(addr); + } else + ret = do_write_mem(file, __va(p), p, buf, count, ppos); return ret; }